/*
 * MODULE  NAME  :
 * PROGRAM NAME  : tkapp.h
 * AUTHOR        : hotmocha(hotmocha@126.com)
 * CREATE  DATE  : 2015-10-21 15:04:46
 * PROGRAM DESC  :
 *
 * HISTORY       :
 *
 */
#ifndef _H_TKAPP_H_
#define _H_TKAPP_H_

#ifndef _FUNCTION_
	#define _FUNCTION_
#endif

#include "tkevent.h"
#include "tklist.h"

struct tk_message {
	int header_len;
	int body_len;
	int body_tmp_len;	/* should send or recv body len */
	char header[HEADERLEN + 1];	/* (4: len, 4: type) total 8 bytes*/
	char body[MAXMESSAGELEN + 1];
};

#define tk_message_buffer(p_tk_msg, p_tk_msg_buffer, p_tk_msg_len)  		\
	do { 									\
		p_tk_msg_buffer = &((p_tk_msg)->body); 				\
		p_tk_msg_len = p_tk_msg->body_len; 				\
	} while(0);
		


#define TK_CONNECT_SYNC_CLIENT_INFO		0
#define TK_CONNECT_SYNC_CLIENT_INFO_DONE	1
#define TK_CONNECT_SYNC_CLIENTS_LIST		2
#define TK_CONNECT_SYNC_CLIENTS_LIST_DONE	3
#define TK_CONNECT_COMMUNICATING		4

struct tk_connect {
	void *client_ptr;	/* point to struct member(only for server) */
	int stage;		

	struct custom_socket *csock;
	struct tk_message send_msg[MAXMESSAGENUM];
	int msg_start;	/* to send */
	int msg_end; 	/* to recv */
	
	struct tk_message recv_msg;

        int finished:1;
        int failed:1;
        int recving_head:1;
        int recving_body:1;
        int sending_head:1;
        int sending_body:1;

	struct list_head list_node;
};

/******************   function start *********************/
/**
create tk_connect and bind tk_connect to custom_socket
@RETURN
	1. tk_connect*
	2. NULL
**/
_FUNCTION_ struct tk_connect* get_tk_connect(struct custom_socket *s);

_FUNCTION_ void destory_tk_connect(struct tk_connect *conn);

/**
init tk_message with body buffer 
@RETURN
	1. TK_TOO_LONG_MESSAGE
	2. TK_OK
**/
_FUNCTION_ int init_tk_message(struct tk_message *msg, char *body, int body_len);

/**
@RETURN
        1. TK_NEED_ADD_W_EVENT
        2. TK_OK
**/
_FUNCTION_ int tk_do_add_send_msg(struct tk_connect *conn, struct tk_message *send_msg);

/***
@RETURN:
        1. TK_AGAIN (internal buffer is full)
        2. TK_ERROR(errno)
        3. TK_DONE(no use)
        4. TK_OK (head sent) should delete event(if non-blocking mode)
        5. TK_NO_MORE_SEND_MSG (attention: other success status) should delete event(if non-blocking mode)
        6. TK_SEND_BODY_DONE: should delete event(if non-blocking mode)
	at most send one message
***/
_FUNCTION_ int tk_do_send_msg(struct tk_connect *conn);
	
/***
@RETURN:
        1. TK_OK (head received) should delete event(if non-blocking mode)
        2. TK_AGAIN (internal buffer is empty)
        3. TK_ERROR(errno)
        4. TK_DONE      (remote close)
        5. TK_RECV_BODY_DONE should delete event(if non-blocking mode)
	at most receive one message
***/
_FUNCTION_ int tk_do_recv_msg(struct tk_connect *conn);

_FUNCTION_ void tk_start_communicate(struct tk_connect *conn);

_FUNCTION_ int tk_connection_error(struct select_env *env, struct tk_connect *conn);
_FUNCTION_ int tk_remote_close(struct select_env *env, struct tk_connect *conn);
	
struct tk_connect* tk_connect_server(struct select_env *env, char *ip, int serverport);
struct tk_message* get_send_message(struct tk_connect *conn);
struct tk_message* get_recv_message(struct tk_connect *conn);
int tk_message_body_len(struct tk_message *msg);
int tk_message_type(struct tk_message *msg);

#endif
